home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / Software / Freeware / Programare / zoomsearch / zoomsearch.exe / {app} / scripts / JavaScript / search.js < prev   
Text File  |  2005-03-10  |  24KB  |  649 lines

  1. // ----------------------------------------------------------------------------
  2. // Zoom Search Engine 4.0 (10/3/2005)
  3. //
  4. // This file (search.js) is the JavaScript search front-end for client side
  5. // searches using index files created by the Zoom Search Engine Indexer.
  6. //
  7. // email: zoom@wrensoft.com
  8. // www: http://www.wrensoft.com
  9. //
  10. // Copyright (C) Wrensoft 2000-2005
  11. //
  12. // This script performs client-side searching with the index data file
  13. // (zoom_index.js) generated by the Zoom Search Engine Indexer. It allows you
  14. // to run searches on mediums such as CD-ROMs, or other local data, where a
  15. // web server is not available.
  16. //
  17. // We recommend against using client-side searches for online websites because
  18. // it requires the entire index data file to be downloaded onto the user's
  19. // local machine. This can be very slow for large websites, and our server-side
  20. // search scripts (search.php and search.asp) are far better suited for this.
  21. // However, JavaScript is still an option for smaller websites in a limited
  22. // hosting situation (eg: no PHP or ASP)
  23. // ----------------------------------------------------------------------------
  24.  
  25. // Include required files for index data, settings, etc.
  26. document.write("<script language=\"JavaScript\" src=\"zoom_index.js\" charset=\"" + Charset + "\"><\/script>");
  27. document.write("<script language=\"JavaScript\" src=\"zoom_pages.js\" charset=\"" + Charset + "\"><\/script>");
  28. document.write("<script language=\"JavaScript\" src=\"zoom_titles.js\" charset=\"" + Charset + "\"><\/script>");
  29. document.write("<script language=\"JavaScript\" src=\"zoom_descriptions.js\" charset=\"" + Charset + "\"><\/script>");
  30.  
  31. document.write("<meta http-equiv=\"content-type\" content=\"text/html; charset=" + Charset + "\">");
  32. if (document.charset)
  33.     document.charset = Charset;    // IE4+ only
  34.  
  35. // ----------------------------------------------------------------------------
  36. // Settings (change if necessary)
  37. // ----------------------------------------------------------------------------
  38.  
  39. // The options available in the dropdown menu for number of results
  40. // per page
  41. var PerPageOptions = new Array(10, 20, 50, 100);
  42.  
  43. // Globals
  44. var SkippedWords = 0;
  45. var searchWords = new Array();
  46. var SkippedOutputStr = "";
  47.  
  48. var months = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
  49.  
  50. // ----------------------------------------------------------------------------
  51. // Helper Functions
  52. // ----------------------------------------------------------------------------
  53.  
  54. // This function will return the value of a GET parameter
  55. function getParam(paramName)
  56. {
  57.     paramStr = document.location.search;
  58.     if (paramStr == "")
  59.         return "";
  60.  
  61.     // remove '?' in front of paramStr
  62.     if (paramStr.charAt(0) == "?")
  63.         paramStr = paramStr.substring(1, paramStr.length);
  64.  
  65.     arg = (paramStr.split("&"));
  66.     for (i=0; i < arg.length; i++) {
  67.         arg_values = arg[i].split("=")
  68.         if (unescape(arg_values[0]) == paramName) {
  69.             if (UseUTF8 == 1 && self.decodeURIComponent) // check if decodeURIComponent() is defined
  70.                 ret = decodeURIComponent(arg_values[1]);
  71.             else
  72.                 ret = unescape(arg_values[1]);  // IE 5.0 and older does not have decodeURI
  73.             return ret;
  74.         }
  75.     }
  76.     return "";
  77. }
  78.  
  79. // Compares the two values, used for sorting output results
  80. // Results that match all search terms are put first, highest score
  81. function SortCompare (a, b)
  82. {
  83.     if (a[2] < b[2]) return 1;
  84.     else if (a[2] > b[2]) return -1;
  85.     else if (a[1] < b[1]) return 1;
  86.     else if (a[1] > b[1]) return -1;
  87.     else return 0;
  88. }
  89.  
  90. function SortByDate(a, b)
  91. {
  92.     if (datetime[a[0]] < datetime[b[0]]) return 1;
  93.     else if (datetime[a[0]] > datetime[b[0]]) return -1;
  94.     else return SortCompare(a, b);
  95. }
  96.  
  97.  
  98. function pattern2regexp(pattern)
  99. {
  100.     pattern = pattern.replace(/\#/g, "\\#");
  101.     pattern = pattern.replace(/\$/g, "\\$");
  102.     pattern = pattern.replace(/\./g, "\\.");
  103.     pattern = pattern.replace(/\*/g, "[\\d\\S]*");
  104.     pattern = pattern.replace(/\?/g, ".?");
  105.     return pattern;
  106. }
  107.  
  108. function HighlightDescription(line) {
  109.     res = " " + line + " ";
  110.     for (i = 0; i < numwords; i++) {
  111.         if (searchWords[i] == "")
  112.             continue;
  113.  
  114.         if (SearchAsSubstring == 1)
  115.             res = res.replace(new RegExp("("+searchWords[i]+")", "gi"), "[;:]$1[:;]");
  116.         else
  117.             res = res.replace(new RegExp("(\\W|^|\\b)("+searchWords[i]+")(\\W|$|\\b)", "gi"), "$1[;:]$2[:;]$3");
  118.     }
  119.     // replace the marker text with the html text
  120.     // this is to avoid finding previous <span>'ed text.
  121.     res = res.replace(/\[;:\]/g, "<span class=\"highlight\">");
  122.     res = res.replace(/\[:;\]/g, "</span>");
  123.     return res;
  124. }
  125.  
  126. function PrintNumResults(num)
  127. {
  128.     if (num == 0)
  129.         return STR_NO_RESULTS;
  130.     else if (num == 1)
  131.         return num + " " + STR_RESULT;
  132.     else
  133.         return num + " " + STR_RESULTS;
  134. }
  135.  
  136.  
  137. function SkipSearchWord(sw) {
  138.     if (searchWords[sw] != "") {
  139.         if (SkippedWords > 0)
  140.             SkippedOutputStr += ", ";
  141.         SkippedOutputStr += "\"<b>" + searchWords[sw] + "</b>\"";
  142.         searchWords[sw] = "";
  143.     }
  144.     SkippedWords++;
  145. }
  146.  
  147.  
  148. // ----------------------------------------------------------------------------
  149. // Parameters initialisation (globals)
  150. // ----------------------------------------------------------------------------
  151.  
  152. var query = getParam("zoom_query");
  153. query = query.replace(/[\++]/g, " ");  // replace the '+' with spaces
  154. query = query.replace(/[,+]/g, " ");
  155. query = query.replace(/\</g, "<");
  156. query = query.replace(/[\"+]/g, " ");
  157.  
  158. var per_page = parseInt(getParam("zoom_per_page"));
  159. if (isNaN(per_page)) per_page = 10;
  160.  
  161. var page = parseInt(getParam("zoom_page"));
  162. if (isNaN(page)) page = 1;
  163.  
  164. var andq = parseInt(getParam("zoom_and"));
  165. if (isNaN(andq))
  166. {
  167.     if (typeof(DefaultToAnd) != "undefined" && DefaultToAnd == 1)
  168.         andq = 1;
  169.     else
  170.         andq = 0;
  171. }
  172.  
  173. var cat = parseInt(getParam("zoom_cat"));
  174. if (isNaN(cat)) cat = -1;   // search all categories
  175.  
  176. // for sorting options. zero is default (relevance)
  177. // 1 is sort by date (if date/time is available)
  178. var sort = parseInt(getParam("zoom_sort"));
  179. if (isNaN(sort)) sort = 0;
  180.  
  181. var SelfURL = "";
  182. if (typeof(LinkBackURL) == "undefined")
  183. {
  184.     SelfURL = document.location.href;
  185.     var paramIndex = SelfURL.indexOf("?");
  186.     if (paramIndex > -1)
  187.         SelfURL = SelfURL.substr(0, paramIndex);    // strip off the parameters
  188. }
  189. else
  190.     SelfURL = LinkBackURL;
  191.  
  192. /*
  193. if (typeof(catnames) != "undefined" && typeof(catpages) != "undefined")
  194.     UseCats = true;
  195. else
  196.     UseCats = false;
  197. */
  198.  
  199. var data = new Array();
  200. var output = new Array();
  201.  
  202. target = "";
  203. if (UseLinkTarget == 1)
  204.     target = " target=\"" + LinkTarget + "\" ";
  205.  
  206.  
  207.  
  208. // ----------------------------------------------------------------------------
  209. // Main search function starts here
  210. // ----------------------------------------------------------------------------
  211.  
  212. function ZoomSearch() {
  213.  
  214.     if (Timing == 1) {
  215.         timeStart = new Date();
  216.     }
  217.  
  218.     // Display the form
  219.     if (FormFormat > 0) {
  220.         document.writeln("<form method=\"get\" action=\"" + SelfURL + "\" class=\"zoom_searchform\">");
  221.         document.writeln("<input type=\"text\" name=\"zoom_query\" size=\"20\" value=\"" + query + "\" class=\"zoom_searchbox\" />");
  222.         document.writeln("<input type=\"submit\" value=\"" + STR_FORM_SUBMIT_BUTTON + "\" class=\"zoom_button\" />");
  223.         if (FormFormat == 2) {
  224.             document.writeln("<span class=\"zoom_options\">" + STR_FORM_RESULTS_PER_PAGE + "\n");
  225.             document.writeln("<select name='zoom_per_page'>");
  226.             for (i = 0; i < PerPageOptions.length; i++) {
  227.                 document.write("<option");
  228.                 if (PerPageOptions[i] == per_page)
  229.                     document.write(" selected=\"selected\"");
  230.                 document.writeln(">" + PerPageOptions[i] + "</option>");
  231.             }
  232.             document.writeln("</select><br /><br />");
  233.             if (UseCats) {
  234.                 document.write(STR_FORM_CATEGORY + " ");
  235.                 document.write("<select name='zoom_cat'>");
  236.                 // 'all cats option
  237.                 document.write("<option value=\"-1\">" + STR_FORM_CATEGORY_ALL + "</option>");
  238.                 for (i = 0; i < catnames.length; i++) {
  239.                     document.write("<option value=\"" + i + "\"");
  240.                     if (i == cat)
  241.                         document.write(" selected=\"selected\"");
  242.                     document.writeln(">" + catnames[i] + "</option>");
  243.                 }
  244.                 document.writeln("</select>  ");
  245.             }
  246.             document.writeln(STR_FORM_MATCH + " ");
  247.             if (andq == 0) {
  248.                 document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"0\" checked=\"checked\" />" + STR_FORM_ANY_SEARCH_WORDS);
  249.                 document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"1\" />" + STR_FORM_ALL_SEARCH_WORDS);                                
  250.             } else {
  251.                 document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"0\" />" + STR_FORM_ANY_SEARCH_WORDS);
  252.                 document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"1\" checked=\"checked\" />" + STR_FORM_ALL_SEARCH_WORDS);                
  253.             }
  254.             document.writeln("<input type=\"hidden\" name=\"zoom_sort\" value=\"" + sort + "\" />");
  255.             document.writeln("</span>");
  256.         }
  257.         else
  258.         {
  259.             document.writeln("<input type=\"hidden\" name=\"zoom_per_page\" value=\"" + per_page + "\" />");
  260.             document.writeln("<input type=\"hidden\" name=\"zoom_and\" value=\"" + andq + "\" />");
  261.             document.writeln("<input type=\"hidden\" name=\"zoom_sort\" value=\"" + sort + "\" />");
  262.         }
  263.         
  264.         document.writeln("</form>");
  265.     }
  266.  
  267.     // give up early if no search words provided
  268.     if (query.length == 0) {
  269.         //document.writeln("No search query entered.<br />");        
  270.         if (ZoomInfo == 1)
  271.             document.writeln("<center><p><small>" + STR_POWEREDBY + " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>");
  272.         return;
  273.     }
  274.  
  275.     if (MapAccents == 1) {
  276.         for (i = 0; i < NormalChars.length; i++) {
  277.             query = query.replace(AccentChars[i], NormalChars[i]);
  278.         }
  279.     }
  280.  
  281.  
  282.     if (ToLowerSearchWords == 1)
  283.         query = query.toLowerCase();
  284.  
  285.     // prepare search query, strip quotes, trim whitespace
  286.     if (WordJoinChars.indexOf(".") == -1)
  287.         query = query.replace(/[\.+]/g, " ");
  288.  
  289.     if (WordJoinChars.indexOf("-") == -1)
  290.         query = query.replace(/[\-+]/g, " ");
  291.  
  292.     if (WordJoinChars.indexOf("_") == -1)
  293.         query = query.replace(/[\_+]/g, " ");
  294.  
  295.     if (WordJoinChars.indexOf("'") == -1)
  296.         query = query.replace(/[\'+]/g, " ");
  297.  
  298.     if (WordJoinChars.indexOf("#") == -1)
  299.         query = query.replace(/[\#+]/g, " ");
  300.  
  301.     if (WordJoinChars.indexOf("$") == -1)
  302.         query = query.replace(/[\$+]/g, " ");
  303.  
  304.     //    if (WordJoinChars.indexOf(",") == -1)
  305.     //      query = query.replace(/[\,+]/g, " ");
  306.  
  307.     // substitute multiple whitespace chars to single character
  308.     query = query.replace(/[\/\s\\\\(\)\^\[\]\|\+\{\}]+/g, " ");    
  309.  
  310.     // trim trailing/leading whitespace
  311.     query = query.replace(/^\s*|\s*$/g,""); 
  312.  
  313.     // split search phrase into words
  314.     searchWords = query.split(" "); // split by spaces.
  315.  
  316.     document.write("<div class=\"searchheading\">" + STR_RESULTS_FOR + " \"" + query + "\"");
  317.     if (UseCats) {
  318.         if (cat == -1)
  319.             document.writeln(" " + STR_RESULTS_IN_ALL_CATEGORIES);
  320.         else
  321.             document.writeln(" " + STR_RESULTS_IN_CATEGORY + " \"" + catnames[cat] + "\"");
  322.     }
  323.     document.writeln("</div><br />");
  324.  
  325.     document.writeln("<div class=\"results\">");
  326.  
  327.     numwords = searchWords.length;
  328.     kw_ptr = 0;
  329.     outputline = 0;
  330.     usewildcards = 0;
  331.     ipage = 0;
  332.     matches = 0;
  333.     var SWord;
  334.     pagesCount = urls.length;
  335.  
  336.     // Initialise a result table the size of all pages
  337.     res_table = new Array(pagesCount);
  338.     for (i = 0; i < pagesCount; i++)
  339.     {
  340.         res_table[i] = new Array(3);
  341.         res_table[i][0] = 0;
  342.         res_table[i][1] = 0;
  343.         res_table[i][2] = 0;
  344.     }
  345.  
  346.     if (skipwords) {
  347.         for (sw = 0; sw < numwords; sw++) {
  348.             // check min length
  349.             if (searchWords[sw].length < MinWordLen) {
  350.                 SkipSearchWord(sw);
  351.                 continue;
  352.             }
  353.             // check skip word list
  354.             for (i = 0; i < skipwords.length; i++) {
  355.                 if (searchWords[sw] == skipwords[i]) {
  356.                     SkipSearchWord(sw);
  357.                     break;
  358.                 }
  359.             }
  360.         }
  361.     }
  362.     
  363.     
  364.     if (SkippedWords > 0)
  365.         document.writeln("<i>" + STR_SKIPPED_FOLLOWING_WORDS + " " + SkippedOutputStr + ".</i><br /><br />");
  366.  
  367.  
  368.     // Begin searching...
  369.     for (sw = 0; sw < numwords; sw++) {
  370.  
  371.         if (searchWords[sw] == "")
  372.             continue;
  373.  
  374.         if (searchWords[sw].indexOf("*") == -1 && searchWords[sw].indexOf("?") == -1) {
  375.             UseWildCards = 0;
  376.         } else {
  377.             UseWildCards = 1;
  378.             searchWords[sw] = pattern2regexp(searchWords[sw]);
  379.             if (SearchAsSubstring == 0)
  380.                 pattern = "^" + searchWords[sw] + "$";
  381.             else
  382.                 pattern = searchWords[sw];
  383.  
  384.             re = new RegExp(pattern, "g");
  385.         }
  386.  
  387.         for (kw_ptr = 0; kw_ptr < dictwords.length; kw_ptr++) {
  388.  
  389.             data = dictwords[kw_ptr].split(",");
  390.  
  391.             if (UseWildCards == 0) {
  392.                 if (SearchAsSubstring == 0)
  393.                     //match_result = data[0].search("^" + SWord + "$");
  394.                     if (data[0] == searchWords[sw])
  395.                         match_result = 0;
  396.                     else
  397.                         match_result = -1;
  398.                 else
  399.                     match_result = data[0].indexOf(searchWords[sw]);
  400.             } else
  401.                 match_result = data[0].search(re);
  402.  
  403.  
  404.             if (match_result != -1) {
  405.                 // keyword found, include it in the output list
  406.  
  407.                 for (kw = 1; kw < data.length; kw += 2) {
  408.                     // check if page is already in output list
  409.                     pageexists = 0;
  410.                     ipage = data[kw];
  411.                     if (res_table[ipage][0] == 0) {
  412.                         matches++;
  413.                         res_table[ipage][0] += parseInt(data[kw+1]);
  414.                     }
  415.                     else {
  416.  
  417.                         if (res_table[ipage][0] > 10000) {
  418.                             // take it easy if its too big to prevent gigantic scores
  419.                             res_table[ipage][0] += 1;
  420.                         } else {
  421.                             res_table[ipage][0] += parseInt(data[kw+1]); // add in score
  422.                             res_table[ipage][0] *= 2;           // double score as we have two words matching
  423.                         }
  424.                     }
  425.                     res_table[ipage][1] += 1;
  426.                     // store the 'and' user search terms matched' value
  427.                     if (res_table[ipage][2] == sw || res_table[ipage][2] == sw-SkippedWords)
  428.                         res_table[ipage][2] += 1;
  429.  
  430.                 }
  431.                 if (UseWildCards == 0 && SearchAsSubstring == 0)
  432.                     break;    // this search word was found, so skip to next
  433.  
  434.             }
  435.         }
  436.  
  437.     }
  438.  
  439.     // Count number of output lines that match ALL search terms
  440.     oline = 0;
  441.     fullmatches = 0;
  442.     ResFiltered = false;
  443.     output = new Array();
  444.     var full_numwords = numwords - SkippedWords;
  445.     for (i = 0; i < pagesCount; i++) {
  446.         IsFiltered = false;
  447.         if (res_table[i][0] != 0) {
  448.             if (UseCats && cat != -1) {
  449.                 // using cats and not doing an "all cats" search
  450.                 if (catpages[i] != cat) {
  451.                     IsFiltered = true;
  452.                 }
  453.             }
  454.             if (IsFiltered == false) {
  455.                 if (res_table[i][2] >= full_numwords) {
  456.                     fullmatches++;
  457.                 } else {
  458.                     if (andq == 1)
  459.                         IsFiltered = true;
  460.                 }
  461.             }
  462.             if (IsFiltered == false) {
  463.                 // copy if not filtered out
  464.                 output[oline] = new Array(3);
  465.                 output[oline][0] = i;
  466.                 output[oline][1] = res_table[i][0];
  467.                 output[oline][2] = res_table[i][1];
  468.                 oline++;
  469.             } else {
  470.                 ResFiltered = true;
  471.             }
  472.         }
  473.     }
  474.     if (ResFiltered == true)
  475.         matches = output.length;
  476.  
  477.     // Sort results in order of score, use "SortCompare" function
  478.     if (matches > 1)    
  479.        {
  480.            if (sort == 1 && UseDateTime == 1)
  481.                output.sort(SortByDate);    // sort by date
  482.            else
  483.             output.sort(SortCompare);    // sort by relevance
  484.     }
  485.     
  486.     // prepare query_out
  487.     var query_out = query.replace(/\s/g, "+");
  488.     query_out = escape(query_out);    
  489.  
  490.     //Display search result information
  491.     document.writeln("<div class=\"summary\">");
  492.     if (matches == 0)
  493.         document.writeln(STR_SUMMARY_NO_RESULTS_FOUND + "<br />");
  494.     else if (numwords > 1 && andq == 0) {
  495.         //OR
  496.         SomeTermMatches = matches - fullmatches;
  497.         document.writeln(PrintNumResults(fullmatches) + " " + STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS + " ");
  498.         if (SomeTermMatches > 0)
  499.             document.writeln(PrintNumResults(SomeTermMatches) + " " + STR_SUMMARY_FOUND_CONTAINING_SOME_TERMS);
  500.         document.writeln("<br />");
  501.     }
  502.     else if (numwords > 1 && andq == 1) //AND
  503.         document.writeln(PrintNumResults(fullmatches) + " " + STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS + "<br />");
  504.     else
  505.         document.writeln(PrintNumResults(matches) + " " + STR_SUMMARY_FOUND + "<br />");
  506.  
  507.     document.writeln("</div>\n");
  508.  
  509.     // number of pages of results
  510.     num_pages = Math.ceil(matches / per_page);
  511.     if (num_pages > 1)
  512.         document.writeln("<br />" + num_pages + " " + STR_PAGES_OF_RESULTS + "<br />\n");
  513.         
  514.     // Show sorting options
  515.     if (matches > 1)
  516.     {
  517.         if (UseDateTime == 1)
  518.         {
  519.             document.writeln("<div class=\"sorting\">");
  520.             if (sort == 1)
  521.                 document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + query_out + "&zoom_page=" + page + "&zoom_per_page=" + per_page + "&zoom_cat=" + cat + "&zoom_and=" + andq + "&zoom_sort=0\">" + STR_SORTBY_RELEVANCE + "</a> / <b>" + STR_SORTEDBY_DATE + "</b>");
  522.             else
  523.                 document.writeln("<b>" + STR_SORTEDBY_RELEVANCE + "</b> / <a href=\"" + SelfURL + "?zoom_query=" + query_out + "&zoom_page=" + page + "&zoom_per_page=" + per_page + "&zoom_cat=" + cat + "&zoom_and=" + andq + "&zoom_sort=1\">" + STR_SORTBY_DATE + "</a>");
  524.             document.writeln("</div>");
  525.         }        
  526.     }    
  527.  
  528.     // determine current line of result from the output array
  529.     if (page == 1) {
  530.         arrayline = 0;
  531.     } else {
  532.         arrayline = ((page - 1) * per_page);
  533.     }
  534.  
  535.     // the last result to show on this page
  536.     result_limit = arrayline + per_page;
  537.  
  538.     // display the results
  539.     while (arrayline < matches && arrayline < result_limit) {
  540.         ipage = output[arrayline][0];
  541.         score = output[arrayline][1];
  542.         
  543.         document.writeln("<p></p>\n");
  544.         
  545.         document.writeln("<div class=\"result_title\">");
  546.         if (DisplayNumber == 1)
  547.             document.writeln("<b>" + (arrayline+1) + ".</b> ");
  548.             
  549.         if (DisplayTitle == 1)
  550.         {
  551.             if (GotoHighlight == 1)                
  552.             {
  553.                 if (SearchAsSubstring == 1)
  554.                     document.writeln("<a href=\"" + urls[ipage] + "?zoom_highlightsub=" + query_out + "\"" + target + ">" + titles[ipage] + "</a>");
  555.                 else
  556.                     document.writeln("<a href=\"" + urls[ipage] + "?zoom_highlight=" + query_out + "\"" + target + ">" + titles[ipage] + "</a>");
  557.             }            
  558.             else                                 
  559.                 document.writeln("<a href=\"" + urls[ipage] + "\"" + target + ">" + titles[ipage] + "</a>");
  560.         }        
  561.         else
  562.             document.writeln("<a href=\"" + urls[ipage] + "\"" + target + ">" + urls[ipage] + "</a>");
  563.                    
  564.         if (UseCats) {
  565.             catindex = catpages[ipage];
  566.             document.writeln("<span class=\"category\">[" + catnames[catindex] + "]</span>");
  567.         }
  568.         document.writeln("</div>");
  569.         
  570.         if (DisplayMetaDesc == 1)
  571.         {
  572.             document.writeln("<div class=\"description\">");
  573.             if (Highlighting == 1)
  574.                 document.writeln(HighlightDescription(descriptions[ipage]));
  575.             else
  576.                 document.writeln(descriptions[ipage]);
  577.             document.writeln("<b>...</b></div>\n");
  578.         }
  579.         
  580.         info_str = "";
  581.         
  582.         if (DisplayTerms == 1)
  583.             info_str += STR_RESULT_TERMS_MATCHED + " " + output[arrayline][2];
  584.             
  585.         if (DisplayScore == 1) {
  586.             if (info_str.length > 0)
  587.                 info_str += "  -  ";
  588.             info_str += STR_RESULT_SCORE + " " + score;
  589.         }
  590.         
  591.         if (DisplayDate == 1) {
  592.             if (info_str.length > 0)
  593.                 info_str += "  -  ";
  594.             info_str += datetime[ipage].getDate() + " " + months[datetime[ipage].getMonth()] + " " + datetime[ipage].getFullYear();
  595.         }
  596.              
  597.         if (DisplayURL == 1) {
  598.             if (info_str.length > 0)
  599.                 info_str += "  -  ";
  600.             info_str += STR_RESULT_URL + " " + urls[ipage];
  601.         }
  602.                    
  603.         document.writeln("<div class=\"infoline\">");
  604.         document.writeln(info_str);                        
  605.         document.writeln("</div>\n");
  606.         arrayline++;
  607.     }
  608.  
  609.     // Show links to other result pages
  610.     if (num_pages > 1) {
  611.         // 10 results to the left of the current page
  612.         start_range = page - 10;
  613.         if (start_range < 1)
  614.             start_range = 1;
  615.  
  616.         // 10 to the right
  617.         end_range = page + 10;
  618.         if (end_range > num_pages)
  619.             end_range = num_pages;
  620.  
  621.         document.writeln("<p></p>" + STR_RESULT_PAGES + " ");
  622.         if (page > 1)
  623.             document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + query_out + "&zoom_page=" + (page-1) + "&zoom_per_page=" + per_page + "&zoom_cat=" + cat + "&zoom_and=" + andq + "&zoom_sort=" + sort + "\"><< " + STR_RESULT_PAGES_PREVIOUS + "</a> ");
  624.  
  625.         for (i = start_range; i <= end_range; i++) {
  626.             if (i == page) {
  627.                 document.writeln(page + " ");
  628.             } else {
  629.                 document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + query_out + "&zoom_page=" + i + "&zoom_per_page=" + per_page + "&zoom_cat=" + cat + "&zoom_and=" + andq + "&zoom_sort=" + sort + "\">" + i + "</a> ");
  630.             }
  631.         }
  632.  
  633.         if (page != num_pages)
  634.             document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + query_out + "&zoom_page=" + (page+1) + "&zoom_per_page=" + per_page + "&zoom_cat=" + cat + "&zoom_and=" + andq + "&zoom_sort=" + sort + "\">" + STR_RESULT_PAGES_NEXT + " >></a> ");
  635.     }
  636.  
  637.     document.writeln("</div>"); // end results style tag
  638.  
  639.     if (Timing == 1) {
  640.         timeEnd = new Date();
  641.         timeDifference = timeEnd - timeStart;
  642.         document.writeln("<br /><br /><small>" + STR_SEARCH_TOOK + " " + (timeDifference/1000) + " " + STR_SECONDS + ".</small>\n");
  643.     }
  644.  
  645.     if (ZoomInfo == 1)
  646.         document.writeln("<center><p><small>" + STR_POWEREDBY + " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>");
  647. }
  648.  
  649.